﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using T.FAS.Runtime.Base.Common;
using T.FAS.Runtime.Base.Dao;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Base.Entity.Tools;
using T.FAS.Runtime.Base.SPI;

namespace T.FAS.Runtime.Base.Service
{
    public class FasMaskService
    {
        private static readonly object s_syncObj = new object();
        private static readonly string s_capturePattern = @"\$(\d+)";
        private static FasMaskService s_instance;
        private static readonly MaskSettingDao _maskDao = new MaskSettingDao();
        /// <summary>
        /// 缓存起来，否则每次查询都要访问fas db
        /// </summary>
        private static List<MaskSetting> s_cache = null;

        private FasMaskService()
        {
            s_cache = GetMaskSettings();
        }

        public static FasMaskService GetInstance()
        {
            if (s_instance == null)
            {
                lock (s_syncObj)
                {
                    if (s_instance == null)
                    {
                        s_instance = new FasMaskService();
                    }
                }
            }

            return s_instance;
        }

        #region 掩码正则相关方法
        /// <summary>
        /// 测试掩码正则表达式正确性，并获取捕获分组
        /// </summary>
        /// <param name="pattern"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool TestMaskPattern(string pattern, string input, out GroupCollection groups)
        {
            Regex regex = new Regex(pattern);
            MatchCollection matches = regex.Matches(input);
            Match match = matches.Count > 0 ? matches[0] : null;
            groups = match?.Groups;
            if (match == null)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 判断掩码替换值是否包含分组捕获
        /// </summary>
        /// <param name="replacement"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool TryGetMatches(string replacement, out MatchCollection matches)
        {
            Regex regex = new Regex(s_capturePattern);
            matches = regex.Matches(replacement);
            return matches.Count > 0;
        }

        /// <summary>
        /// 尝试获取掩码值结果
        /// </summary>
        /// <param name="replacement"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool TryGetMaskData(string pattern, string replacement, string input, out string result)
        {
            result = replacement;
            try
            {
                result = MaskRegTool.GetMaskDataInternal(input, pattern, replacement);
                return true;
            }
            catch
            {
                return false;
            }
            //return TryGetMaskDataInternal(pattern, replacement, input, ref result);
        }
         
        private bool TryGetMaskDataInternal(string pattern, string replacement, string input, ref string result)
        {
            try
            {
                if (!TestMaskPattern(pattern, input, out GroupCollection groups)) return false;
                if (TryGetMatches(replacement, out MatchCollection captureMatches))
                {
                    if (groups.Count - 1 < captureMatches.Count)
                    {
                        //当替换值的分组捕获数量小于输入值的捕获数量时，返回失败
                        return false;
                    }
                    int offset = 0;
                    for (int i = 0; i < captureMatches.Count; i++)
                    {
                        string repVal = groups[i + 1].Value ?? "";
                        Match matchItem = captureMatches[i];
                        int start = matchItem.Index + offset; // 获取匹配位置的偏移量
                        int length = matchItem.Length;

                        // 在原始字符串中进行替换
                        result = result.Remove(start, length).Insert(start, repVal);

                        // 更新偏移量
                        offset += repVal.Length - length;
                    }
                }
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        #endregion

        #region 掩码规则读取方法
        /// <summary>
        /// 获取掩码设置，供统一数据访问服务使用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public MaskSetting GetMaskSetting(string id)
        {
            //优先走sys的统一掩码规则
            if (ConfigUtil.Instance.SYSPublicMaskConfig != null)
            {
                SYSMaskConfig sysMask = ConfigUtil.Instance.SYSPublicMaskConfig.FirstOrDefault(c => c.Type == id);
                if (sysMask != null)
                {
                    return Mapping(sysMask);
                }
            }
            return s_cache?.FirstOrDefault(s => s.ID == id);
            return _maskDao.GetRuleById(id);
        }

        /// <summary>
        /// 获取掩码设置
        /// </summary>
        /// <returns></returns>
        private static List<MaskSetting> GetMaskSettings()
        {
            return _maskDao.GetAllRules();
        }

        private MaskSetting Mapping(SYSMaskConfig sysMask)
        {
            return new MaskSetting
            {
                ID = sysMask.Type,
                RegPattern = sysMask.Pattern,
                Replacement = sysMask.Replacement,
                RuleName = sysMask.Description,
            };
        }
        #endregion
    }
}